/**
 * 
 */
package com.jonosoft.photocast.viewer.web.client.ui;

import java.util.ArrayList;
import java.util.Iterator;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LoadListener;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.jonosoft.photocast.viewer.web.client.ImageCollection;
import com.jonosoft.photocast.viewer.web.client.Web;
import com.jonosoft.photocast.viewer.web.client.debug.Logger;
import com.jonosoft.photocast.viewer.web.client.util.Size;

/**
 * TODO Add description ImageGrid (com.jonosoft.photocast.viewer.web.client.ImageGrid)
 *
 * @author jon
 *
 */
public class ThumbnailsPanel extends Composite implements ClickListener {
	
	private static final String STYLE_NAME = "thumbnails-panel";

	private static final Size SIZE_DEFAULT = null;
	private static final Size SIZE_SMALL = new Size(150, 150);
	private static final Size SIZE_MEDIUM = new Size(280, 280);
	private static final Size SIZE_LARGE = new Size(810, 810);

	private ImageBrowser imageBrowserRef = null;
	private ImageCollection imageCollection = null;
	private Size imageSize = SIZE_SMALL;
	private String flexibleImageSize = null;
	private int imageSpacing = 2;
	private int backgroundColorGrayValue = 0;
	private final VerticalPanel panel = new VerticalPanel();
	private final FlowPanel thumbnailsFlowPanel = new FlowPanel();
	private final DeferredImagePopulator deferredImagePopulator = new DeferredImagePopulator(thumbnailsFlowPanel, this);
	private final ImageSizePanel imageSizePanel = new ImageSizePanel();
	private final Size imageSizePanelSize = new Size(0, 35);
	private final Size thumbnailsPanelSize = new Size();

	public ThumbnailsPanel(ImageBrowser imageBrowserRef, ArrayList imageURLs) {
		initWidget(panel);
		
		this.imageBrowserRef = imageBrowserRef;
		
		panel.add(imageSizePanel);
		panel.add(thumbnailsFlowPanel);
		
		panel.setStyleName(STYLE_NAME + "-wrapper");

    	thumbnailsFlowPanel.setStyleName(STYLE_NAME);
    	thumbnailsFlowPanel.setWidth("100%");
    	
    	flexibleImageSize = getFlexibleWidth(imageSize.getWidth().intValue());
		
		setImages(imageCollection);
	}

	public ImageCollection getImages() {
    	return this.imageCollection;
    }

	public void setImages(ImageCollection imageCollection) {
    	this.imageCollection = imageCollection;
    }
    
    public void setImageSize(Size imageSize) {
    	String width = null;
    	String height = null;
    	int displayType = -1;
    	
    	this.imageSize = imageSize;
    	
    	displayType = getDisplayType();
    	
    	if (imageSize == null)
    		width = height = "auto";
    	else {
    		width = getFlexibleWidth(imageSize.getWidth().intValue());
    		height = imageSize.getCSSHeight();
    	}
    	
    	Iterator imageIterator = this.imageCollection.iterator();
    	
    	while (imageIterator.hasNext()) {
    		LibraryImage image = (LibraryImage) imageIterator.next(); 
    		resizeImage(image, width, height);
    		image.setDisplayType(displayType);
    	}
    }
    
    private void resizeImage(LibraryImage image, String width) {
    	image.setWidth(width);
    }
    
    private void resizeImage(LibraryImage image, String width, String height) {
    	image.setWidth(width);
    	image.setHeight(height);
    }
    
    private void adjustFlexibleImageWidths() {
    	if (imageSize == null)
    		return;
    	
    	String width = getFlexibleWidth(imageSize.getWidth().intValue());
    	
    	Iterator imageIterator = imageCollection.iterator();
    	
    	while (imageIterator.hasNext())
    		resizeImage((LibraryImage) imageIterator.next(), width);
    }
    
    private int getNumberOfImagesAcross(int width) {
    	final int offsetWidth = thumbnailsFlowPanel.getOffsetWidth();
    	return (int) Math.floor(offsetWidth / width);
    }
    
    private String getFlexibleWidth(int width) {
		final int percent = (int) Math
		        .floor(100 / getNumberOfImagesAcross(width));
    	return new Integer(percent).toString() + "%";
    }
    
    private int getDisplayType() {
    	return imageSize == SIZE_DEFAULT ? 0
    			: imageSize == SIZE_SMALL ? 1
    					: imageSize == SIZE_MEDIUM ? 2
    							: imageSize == SIZE_LARGE ? 3
    									: 0;
    }
	
    public void populateImageGrid() {
    	if (imageCollection != null) {
    		deferredImagePopulator.populateImages(imageCollection);
    	}
    }
    
    private class DeferredImagePopulator implements LoadListener, Command {
    	
    	private ClickListener clickListener = null;
    	private ImageCollection imageCollection = null;
    	private Iterator imageCollectionIterator = null;
    	private ComplexPanel imagesPanel = null;
    	private boolean isRunning = false;
    	private final Size size = new Size();
    	private int displayType = 0;

		public DeferredImagePopulator(ComplexPanel panel, ClickListener clickListener) {
        	this.imagesPanel = panel;
        	this.clickListener = clickListener;
        }
		
		public void populateImages(ImageCollection imageCollection) {
			this.imageCollection = imageCollection;
			this.imageCollectionIterator = imageCollection.iterator();
			
			imagesPanel.clear();
	    	
	    	if (imageSize == null)
	    		size.setSize(null, null);
	    	else {
				size.setSize(imageSize.getWidth(), imageSize.getHeight());
	    	}
	    	
			this.displayType = getDisplayType();
			
			if (!isRunning)
				nextImage();
		}

		/**
         * @see com.google.gwt.user.client.Command#execute()
         */
        public void execute() {
        	nextImage();
        }
		
		/**
		 * @see com.google.gwt.user.client.ui.LoadListener#onError(com.google.gwt.user.client.ui.Widget)
		 */
		public void onError(Widget sender) {
			try {
				Image img = (Image) sender;
				Logger.debug("Error loading image: " + img.getUrl());
				nextImage();
			}
			catch (Exception ignored) {
				return;
			}
		}
		
		/**
		 * @see com.google.gwt.user.client.ui.LoadListener#onLoad(com.google.gwt.user.client.ui.Widget)
		 */
		public void onLoad(Widget sender) {
			try {
				Image img = (Image) sender;
				Logger.debug("Loaded image: " + img.getUrl());
				nextImage();
			}
			catch (Exception ignored) {
				return;
			}
		}
        
        private void nextImage() {
        	int count = 0;
        	
        	while (imageCollectionIterator.hasNext()) {
        		LibraryImage image = (LibraryImage) imageCollectionIterator.next();

				resizeImage(image, size.getCSSWidth(), size.getCSSHeight());
				image.setDisplayType(displayType);
        		
        		image.addClickListener(clickListener);
        		
        		imagesPanel.add(image);
        		
        		if (imageCollectionIterator.hasNext()) {
        			isRunning = true;
        			if (++count % 3 == 0) {
        				DeferredCommand.add(this);
        				
        				if (count >= getNumberOfImagesAcross(size.getWidth().intValue()))
        					Web.photocastViewer.resize();
        				
        				return;
        			}
        		}
        	}
        	
        	Web.photocastViewer.resize();
        	
        	isRunning = false;
        }
    	
    }

	/**
     * @see com.google.gwt.user.client.ui.ClickListener#onClick(com.google.gwt.user.client.ui.Widget)
     */
    public void onClick(Widget sender) {
    	
    	LibraryImage image = (LibraryImage) sender;

    	Window.open(image.getImageUrl(), "_blank", "");
    }
	
	private class ImageSizePanel extends Composite implements ClickListener {
		private final HorizontalPanel panel = new HorizontalPanel();
		
		private final RadioButton defaultButton = new RadioButton(this.toString(), "Default");
		private final RadioButton smallButton = new RadioButton(this.toString(), "Small");
		private final RadioButton mediumButton = new RadioButton(this.toString(), "Medium");
		private final RadioButton largeButton = new RadioButton(this.toString(), "Large");
		
        public ImageSizePanel() {
        	initWidget(panel);
        	
        	//panel.add(defaultButton);
        	panel.add(smallButton);
        	panel.add(mediumButton);
        	//panel.add(largeButton);
        	
        	//defaultButton.addClickListener(this);
        	smallButton.addClickListener(this);
        	mediumButton.addClickListener(this);
        	//largeButton.addClickListener(this);
        }
        
        public void onClick(Widget sender) {
        	Size imageSize = sender == defaultButton ? SIZE_DEFAULT
        			: sender == smallButton ? SIZE_SMALL
        					: sender == mediumButton ? SIZE_MEDIUM
        							: sender == largeButton ? SIZE_LARGE
        									: null;
        	setImageSize(imageSize);
        }
        
        public void resize(Size size) {
        	panel.setHeight(size.getCSSHeight());
        }
	}

	/**
     * TODO Add method description for resize
     *
     * @param size
     */
    public void resize(Size size) {
    	adjustFlexibleImageWidths();
    	
    	imageSizePanel.resize(imageSizePanelSize);
    	
    	thumbnailsPanelSize.setSize(0, size.getHeight().intValue() - imageSizePanelSize.getHeight().intValue());
    	
    	panel.setHeight(size.getCSSHeight());
    	
    	thumbnailsFlowPanel.setHeight(thumbnailsPanelSize.getCSSHeight());
    }

}
